26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
52 #pragma package(smart_init)
62 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
63 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
64 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
65 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
66 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
67 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
78 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
79 AnsiString(TrainModeIn));
123 for(
int x = 0; x < 4; x++)
132 for(
int x = 0; x < 4; x++)
141 for(
int x = 0; x < 4; x++)
146 for(
int x = 0; x < 4; x++)
150 for(
int x = 0; x < 3; x++)
187 for(
int x = 0; x < 4; x++)
234 throw Exception(
"Error in attempting to delete FrontCodePtr");
238 for(
int x = 0; x < 4; x++)
242 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
247 for(
int x = 0; x < 4; x++)
251 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
280 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
346 bool TempDerail =
false;
392 else if((NextElementPosition > -1) && (NextEntryPos > -1))
463 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
473 for(
int x = 0; x < 4; x++)
480 for(
int x = 0; x < 4; x++)
723 if((random(RandRange)) == 0)
738 int LockedVectorNumber;
975 if(BufferLocation ==
"")
980 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1042 int NextElementPosition, NextEntryPos;
1066 NextElementPosition = -1;
1069 if((NextElementPosition > -1) && (NextEntryPos > -1))
1183 AnsiString StationName;
1194 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1207 if((NextElementPosition > -1) && (NextEntryPos > -1))
1330 if(NextElementPosition > -1)
1367 AnsiString Loc =
"";
1368 bool LocNamed =
false;
1397 Loc =
"outside railway";
1429 NextElementPosition = -1;
1440 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1458 if((NextElementPosition > -1) && (NextEntryPos > -1))
1496 FirstPair.second).
GetELink() == TempELink))
1501 SecondPair.second).
GetELink() == TempELink))
1515 FirstPair.second).
GetELink() == TempELink))
1520 SecondPair.second).
GetELink() == TempELink))
1534 FirstPair.second).
GetELink() == TempELink))
1539 SecondPair.second).
GetELink() == TempELink))
1569 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1572 int NewLastElement = 0, NewLastExitPos = 0;
1590 if(NewLastElement == -1)
1593 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1596 if(NewLastExitPos == -1)
1598 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1600 LastElement = NewLastElement;
1601 LastExitPos = NewLastExitPos;
1604 if(CumDistance < 1200)
1610 int FirstDistance = 0;
1611 if(CumDistance >= 1200)
1613 FirstDistance = 100;
1617 FirstDistance = 1200 - CumDistance;
1619 if(FirstDistance < 100)
1621 FirstDistance = 100;
1647 if(VectorIT->RouteNumber == RouteNumber)
1694 LockedVectorNumber)))
1853 for(
int x = 0; x < 4; x++)
1860 for(
int x = 0; x < 4; x++)
1886 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
1891 if(OtherTrainEntryPos == -1)
1893 throw Exception(
"Error - OtherTrainEntryPos not set");
1912 int OtherTrainID = -1;
1913 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2004 bool StopRequired =
false;
2017 int NextElementEntryPos = -1;
2018 int NextElementExitPos = -1;
2019 bool TrainOnNextElement =
false;
2020 bool StopSignalAtNextElement =
false;
2021 if(ForwardConnection)
2029 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2032 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2087 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2300 if(Code.Length() != 4)
2304 for(
int x = 1; x < 5; x++)
2311 for(
int x = 0; x < 4; x++)
2475 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2488 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2503 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2512 TRect SourceRect, DestRect;
2514 DestRect.init(0, 0, 8, 8);
2517 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2519 TempGraphic->PixelFormat = pf8bit;
2520 TempGraphic->Width = 16;
2521 TempGraphic->Height = 16;
2527 TempGraphic->Transparent =
true;
2531 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2532 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2538 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2546 else if(TempElement.
SpeedTag == 89)
2550 else if(TempElement.
SpeedTag == 90)
2554 else if(TempElement.
SpeedTag == 91)
2558 else if(TempElement.
SpeedTag == 92)
2562 else if(TempElement.
SpeedTag == 93)
2566 else if(TempElement.
SpeedTag == 94)
2570 else if(TempElement.
SpeedTag == 95)
2574 TempGraphic->Transparent =
true;
2578 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2579 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2581 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2588 for(
int x = 0; x < 40; x++)
2603 TempGraphic->Transparent =
true;
2607 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2608 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2610 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2624 TempGraphic->Transparent =
true;
2628 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2629 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2633 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2636 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2641 TempGraphic->Transparent =
true;
2645 int BDVectorPos = -1;
2654 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2659 TempGraphic->Transparent =
true;
2663 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2664 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2666 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2672 TempGraphic->Transparent =
true;
2676 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2677 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2679 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2945 throw Exception(
"Error, same train on two different bridge tracks");
2991 AnsiString(EntryPos) +
"," +
HeadCode);
3008 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3027 AnsiString(EntryPos) +
"," +
HeadCode);
3036 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3069 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3070 int LockedVectorNumber;
3083 TRect SourceRect, DestRect;
3084 DestRect.init(0, 0, 8, 8);
3091 int FirstELink, SecondELink = -1;
3094 if(RoutePair2.first > -1)
3103 if(SecondELink == -1)
3105 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3110 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3120 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3121 DestGraphic->PixelFormat = pf8bit;
3122 DestGraphic->Width = 8;
3123 DestGraphic->Height = 8;
3124 DestGraphic->Transparent =
true;
3127 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3136 PrefDirElement, LockedVectorNumber))
3151 if(ElementEntryPos > 1)
3173 AnsiString(EntryPos) +
"," +
HeadCode);
3175 bool WrongRoute =
false;
3201 int LinkNumber = TrackElement.
Link[EntryPos];
3202 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3207 bool LogActionErrorCalled =
false;
3217 LogActionErrorCalled =
true;
3234 else if(LinkNumber == 3)
3242 LogActionErrorCalled =
true;
3259 else if(LinkNumber == 7)
3267 LogActionErrorCalled =
true;
3284 else if(LinkNumber == 9)
3292 LogActionErrorCalled =
true;
3324 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3329 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3339 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3344 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3353 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3374 bool ColourError =
false, ColourError2 =
false;
3379 ColourError2 =
true;
3381 for(
int x = 0; x < 4; x++)
3386 ColourError2 =
true;
3392 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3396 for(
int x = 0; x < 4; x++)
3483 AnsiString(EntryPos) +
"," +
HeadCode);
3484 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3485 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3486 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3487 TrainInFrontInSignallerModeFlag =
false;
3488 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3489 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3490 bool SignallerStopRequired =
false;
3501 if(CurrentTrackVectorPosition > -1)
3505 if((EntryPos == 0) || (EntryPos == 2))
3518 else if(EntryPos == 1)
3542 EntryHalfLength = CurrentElementHalfLength;
3547 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3551 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3598 FrontElementMaxSpeed = LimitingSpeed;
3628 double ExitSpeedAtMaxBraking;
3633 ExitSpeedAtMaxBraking = 0;
3643 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3645 SpeedToUse = ExitSpeedAtMaxBraking;
3649 SpeedToUse = LimitingSpeed;
3664 RedSignalFlag =
false;
3665 BuffersFlag =
false;
3666 StationFlag =
false;
3667 BuffersOrContinuationNowFlag =
false;
3668 ContinuationNextFlag =
false;
3671 CumulativeLength += (2 * CurrentElementHalfLength);
3674 SignallerStopRequired =
true;
3696 bool StopRequired =
false;
3710 StationFlag =
false;
3716 BuffersOrContinuationNowFlag =
true;
3718 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3722 if((EntryPos == 0) || (EntryPos == 2))
3744 if(NextTrackVectorPosition > -1)
3749 if((NextEntryPos == 0) || (NextEntryPos == 2))
3762 else if(NextEntryPos == 1)
3775 if(NextEntryPos > 1)
3789 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
3801 RedSignalFlag =
true;
3823 TrainInFrontInSignallerModeFlag =
true;
3847 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
3859 double MaxHalfSpeed;
3863 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
3865 MaxHalfSpeed = FrontElementMaxSpeed;
3869 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
3877 bool HalfSpeedLimited =
false;
3881 HalfSpeedLimited =
true;
3911 if(HalfSpeedLimited)
3936 if(SignallerStopRequired)
3952 int TempMaxExitSpeed;
3955 if(MaxExitSpeedAtHalfBrakingSquared < 10)
3957 MaxExitSpeedAtHalfBraking = 0;
3961 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
3965 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
3967 TempMaxExitSpeed = FrontElementMaxSpeed;
3971 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
3983 if(ExitSpeedHalfSquared < 10)
3993 if(ExitSpeedFullSquared < 10)
4065 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4066 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4090 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4091 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4101 if(!BuffersOrContinuationNowFlag)
4103 if(NextSpeedLimit < LimitingSpeed)
4105 LimitingSpeed = NextSpeedLimit;
4109 int TempMaxExitSpeed;
4113 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4115 MaxExitSpeedAtHalfBraking = 0;
4119 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4121 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4123 TempMaxExitSpeed = FrontElementMaxSpeed;
4127 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4138 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4151 if(!BuffersOrContinuationNowFlag)
4153 CurrentTrackVectorPosition = NextTrackVectorPosition;
4154 EntryPos = NextEntryPos;
4155 CurrentElementHalfLength = NextElementHalfLength;
4158 ContinuationNextFlag =
true;
4162 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4182 if(ExitSpeedHalfSquared < 10)
4192 if(ExitSpeedFullSquared < 10)
4255 double DeltaExitTimeToMaxInSecs;
4256 double DistanceToMax;
4265 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4267 DistanceToMax = EntryHalfLength;
4270 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4271 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4288 double DeltaExitTimeToMaxInSecs;
4289 double DistanceToMax;
4298 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4300 DistanceToMax = EntryHalfLength / 2;
4303 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4304 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4315 if(ExitSpeedHalfSquared < 10)
4325 if(ExitSpeedFullSquared < 10)
4344 if((EntryPos == 0) || (EntryPos == 2))
4366 if(NextTrackVectorPosition > -1)
4368 int NextElementLength;
4369 if(NextEntryPos > 1)
4377 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4513 if((Ptr->Command ==
"cdt") || (Ptr->FormatType ==
Repeat))
4517 if((Ptr->ArrivalTime > TDateTime(-1)) && (Ptr->LocationName == Name))
4526 if((Ptr->EventTime > TDateTime(-1)) && (Ptr->LocationName == Name) && (Ptr->Command ==
"pas"))
4551 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4569 CurrentTrackVectorPosition).
Attribute != 4))
4608 if((EntryPos == 0) || (EntryPos == 2))
4630 CurrentTrackVectorPosition = NextTrackVectorPosition;
4631 EntryPos = NextEntryPos;
4655 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4679 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4680 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4681 int RouteStartPosition;
4683 int PlatformPosition;
4685 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4701 if(Distance > (4000 + LeadElementDistance))
4724 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
4727 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
4773 if(!PlatformFoundFlag)
4775 PlatformPosition = CurrentTrackVectorPosition;
4778 PlatformFoundFlag =
true;
4794 if((EntryPos == 0) || (EntryPos == 2))
4838 if(ElementNumber < 2)
4840 SkipRouteCheck =
true;
4844 SkipRouteCheck =
false;
4846 if(ElementNumber == 1)
4848 RouteStartPosition = CurrentTrackVectorPosition;
4858 if(ElementNumber > 1)
4862 RouteOrPartRouteSet =
true;
4866 RouteOrPartRouteSet =
false;
4869 if(!SkipRouteCheck && !RouteOrPartRouteSet)
4876 int ExitLink = CurrentTrackElement.
Link[ExitPos];
4877 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
4889 Distance += CurrentTrackElement.
Length01;
4893 Distance += CurrentTrackElement.
Length23;
4895 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
4896 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
4897 CurrentTrackVectorPosition = NextTrackVectorPosition;
4898 EntryPos = NextEntryPos;
4935 return(RepeatHeadCode);
4957 bool FrontValid =
false, RearValid =
false;
4958 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
4962 TrainToBeJoinedBy = NULL;
4976 int TrainToBeJoinedByID = -1;
4997 if((TrainToBeJoinedByID < 0) && RearValid)
5016 if(TrainToBeJoinedByID < 0)
5018 TrainToBeJoinedBy = NULL;
5023 if(!TrainToBeJoinedBy->
Stopped())
5025 TrainToBeJoinedBy = NULL;
5036 TDateTime TimetableNonRepeatTime,
bool Warning)
5071 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5072 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5073 int IntMinsLate = 0;
5078 ActionLog =
" arrived at ";
5087 ActionLog =
" terminated at ";
5092 ActionLog =
" departed from ";
5094 if(ActionType ==
Pass)
5096 ActionLog =
" passed ";
5100 ActionLog =
" created at ";
5102 if(ActionType ==
Enter)
5104 ActionLog =
" entered railway at ";
5106 if(ActionType ==
Leave)
5108 ActionLog =
" left railway at ";
5112 ActionLog =
" split from front to ";
5116 ActionLog =
" split from rear to ";
5120 ActionLog =
" joined by ";
5124 ActionLog =
" changed direction at ";
5128 ActionLog =
" became new service ";
5132 ActionLog =
" taken under signaller control at ";
5136 ActionLog =
" restored to timetable control at ";
5142 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5146 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5150 ActionLog =
" REMOVED FROM RAILWAY at ";
5155 ActionLog =
" received signaller authority to proceed";
5159 ActionLog =
" received signaller authority to step forward";
5163 ActionLog =
" changed direction under signaller control at ";
5167 ActionLog =
" received signaller authority to pass red signal";
5171 ActionLog =
" received signaller instruction to stop";
5175 ActionLog =
" stopped on signaller instruction ";
5179 ActionLog =
" joined under signaller control by ";
5183 ActionLog =
" suffered an onboard power failure at ";
5187 ActionLog =
" failure repaired at ";
5191 ActionLog =
" left railway under signaller control at ";
5193 if(OtherHeadCode !=
"")
5195 OtherHeadCode +=
" at ";
5202 WarningBaseLog =
HeadCode + ActionLog + OtherHeadCode + LocationName;
5208 bool TimePerformance =
true;
5216 TimePerformance =
false;
5220 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5222 if(ActionType ==
Pass)
5236 IntMinsLate = int(ceil(MinsLate));
5240 IntMinsLate = int(floor(MinsLate));
5242 if(IntMinsLate == 0)
5244 PerfLog =
" on time";
5246 else if(IntMinsLate == 1)
5248 PerfLog =
" 1 minute late";
5250 else if(IntMinsLate == -1)
5252 PerfLog =
" 1 minute early";
5254 else if(IntMinsLate > 1)
5256 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5258 else if(IntMinsLate < -1)
5260 int PosIntMinsLate = -IntMinsLate;
5261 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5263 if(LocationName.Pos(
'-') > 0)
5265 PerfLog =
"," + PerfLog;
5279 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5283 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5288 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5294 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5298 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5303 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5309 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5313 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5318 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5324 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5328 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5347 AnsiString LocName =
"";
5413 if(LocationName ==
"")
5417 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5418 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5419 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5423 if(LocationName !=
"")
5431 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5436 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5450 int LeadPosA = FirstNamedElementPos;
5451 int LeadPosB = FirstNamedLinkedElementPos;
5452 int LeadPosC = SecondNamedElementPos;
5453 int LeadPosD = SecondNamedLinkedElementPos;
5455 int LeadNumAtLoc = 0;
5472 if(LeadNumAtLoc < 4)
5476 SecondNamedLinkedElementPos))
5478 FirstNamedElementPos = LeadPosA;
5479 FirstNamedLinkedElementPos = LeadPosB;
5480 SecondNamedElementPos = LeadPosC;
5481 SecondNamedLinkedElementPos = LeadPosD;
5485 int MidNumAtLoc = 0;
5502 if(LeadNumAtLoc > MidNumAtLoc)
5505 FirstNamedElementPos = LeadPosA;
5506 FirstNamedLinkedElementPos = LeadPosB;
5507 SecondNamedElementPos = LeadPosC;
5508 SecondNamedLinkedElementPos = LeadPosD;
5522 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5532 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5533 FrontTrainRearPosition = FirstNamedElementPos;
5534 RearTrainFrontPosition = SecondNamedElementPos;
5535 RearTrainRearPosition = SecondNamedLinkedElementPos;
5539 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5540 FrontTrainRearPosition = SecondNamedElementPos;
5541 RearTrainFrontPosition = FirstNamedElementPos;
5542 RearTrainRearPosition = FirstNamedLinkedElementPos;
5549 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5550 FrontTrainRearPosition = SecondNamedElementPos;
5551 RearTrainFrontPosition = FirstNamedElementPos;
5552 RearTrainRearPosition = FirstNamedLinkedElementPos;
5556 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5557 FrontTrainRearPosition = FirstNamedElementPos;
5558 RearTrainFrontPosition = SecondNamedElementPos;
5559 RearTrainRearPosition = SecondNamedLinkedElementPos;
5562 RearTrainExitPos = -1;
5563 for(
int x = 0; x < 4; x++)
5567 RearTrainExitPos = x;
5571 if(RearTrainExitPos == -1)
5573 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5575 FrontTrainExitPos = -1;
5576 for(
int x = 0; x < 4; x++)
5580 FrontTrainExitPos = x;
5584 if(FrontTrainExitPos == -1)
5586 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5589 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5596 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5616 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5624 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5625 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5626 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5723 if(LocationName ==
"")
5727 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5728 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5729 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5733 if(LocationName !=
"")
5740 SecondNamedLinkedElementPos))
5744 SecondNamedLinkedElementPos))
5758 int LeadPosA = FirstNamedElementPos;
5759 int LeadPosB = FirstNamedLinkedElementPos;
5760 int LeadPosC = SecondNamedElementPos;
5761 int LeadPosD = SecondNamedLinkedElementPos;
5763 int LeadNumAtLoc = 0;
5780 if(LeadNumAtLoc < 4)
5784 SecondNamedLinkedElementPos))
5786 FirstNamedElementPos = LeadPosA;
5787 FirstNamedLinkedElementPos = LeadPosB;
5788 SecondNamedElementPos = LeadPosC;
5789 SecondNamedLinkedElementPos = LeadPosD;
5793 int MidNumAtLoc = 0;
5810 if(LeadNumAtLoc > MidNumAtLoc)
5813 FirstNamedElementPos = LeadPosA;
5814 FirstNamedLinkedElementPos = LeadPosB;
5815 SecondNamedElementPos = LeadPosC;
5816 SecondNamedLinkedElementPos = LeadPosD;
5830 throw Exception(
"Error - LocationName not set in RearTrainSplit");
5840 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5841 FrontTrainRearPosition = FirstNamedElementPos;
5842 RearTrainFrontPosition = SecondNamedElementPos;
5843 RearTrainRearPosition = SecondNamedLinkedElementPos;
5847 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5848 FrontTrainRearPosition = SecondNamedElementPos;
5849 RearTrainFrontPosition = FirstNamedElementPos;
5850 RearTrainRearPosition = FirstNamedLinkedElementPos;
5857 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5858 FrontTrainRearPosition = SecondNamedElementPos;
5859 RearTrainFrontPosition = FirstNamedElementPos;
5860 RearTrainRearPosition = FirstNamedLinkedElementPos;
5864 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5865 FrontTrainRearPosition = FirstNamedElementPos;
5866 RearTrainFrontPosition = SecondNamedElementPos;
5867 RearTrainRearPosition = SecondNamedLinkedElementPos;
5870 RearTrainExitPos = -1;
5871 for(
int x = 0; x < 4; x++)
5875 RearTrainExitPos = x;
5879 if(RearTrainExitPos == -1)
5881 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
5883 FrontTrainExitPos = -1;
5884 for(
int x = 0; x < 4; x++)
5888 FrontTrainExitPos = x;
5892 if(FrontTrainExitPos == -1)
5894 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
5897 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5904 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5924 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5932 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5933 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5934 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6073 TTrain *TrainToBeJoinedBy;
6106 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6108 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6165 int RouteNumber = -1;
6173 bool FirstPass =
true;
6178 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6281 for(
int x = 0; x < IncNum; x++)
6314 else if(Ptr->
Command ==
"jbo")
6325 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6331 bool IncludeFER =
false;
6339 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6344 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6355 else if(Ptr->
Command ==
"Fjo")
6361 else if(Ptr->
Command ==
"Frh")
6371 else if(Ptr->
Command ==
"Frh-sh")
6422 else if(Ptr->
Command ==
"jbo")
6427 else if(Ptr->
Command ==
"cdt")
6435 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6807 int RouteNumber = -1;
6815 bool FirstPass =
true;
6820 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6848 ",FloatingLabelNextString" +
"," +
HeadCode);
6849 AnsiString RetStr =
"", LocationName =
"";
6853 throw Exception(
"Error - start entry in FloatingLabelNextString");
6893 else if(Ptr->
Command ==
"Fns")
6899 else if(Ptr->
Command ==
"F-nshs")
6930 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6932 else if(Ptr->
Command ==
"Frh")
6934 RetStr =
"None, train terminated at " + Ptr->
LocationName;
6936 else if(Ptr->
Command ==
"Fer")
6938 AnsiString AllowedExits =
"";
6941 else if(Ptr->
Command ==
"Fjo")
6946 else if(Ptr->
Command ==
"jbo")
6951 else if(Ptr->
Command ==
"fsp")
6956 else if(Ptr->
Command ==
"rsp")
6961 else if(Ptr->
Command ==
"cdt")
6974 + AnsiString(RptNum) +
",CheckNewServiceDepartureTime," +
HeadCode);
6975 AnsiString DepTime =
"", EventTime =
"";
6976 bool CDTFlag =
false;
6980 if(AVI->Command ==
"cdt")
6985 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
6988 RetStr +=
"\nNew service splits at " + EventTime;
6992 if(AVI->Command ==
"jbo")
6995 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
6999 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7004 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7008 RetStr +=
"\nNew service departs at " + DepTime;
7024 ",FloatingTimetableString" +
"," +
HeadCode);
7025 AnsiString RetStr =
"", PartStr =
"";
7031 throw Exception(
"Error - start entry in FloatingTimetableString");
7034 bool FirstPass =
true;
7047 AnsiString TrainLoc =
"";
7085 AnsiString TrainLoc =
"";
7113 else if(Ptr->
Command ==
"Fns")
7119 else if(Ptr->
Command ==
"F-nshs")
7152 else if(Ptr->
Command ==
"Frh")
7156 else if(Ptr->
Command ==
"Fer")
7158 AnsiString AllowedExits =
"";
7161 else if(Ptr->
Command ==
"Fjo")
7166 else if(Ptr->
Command ==
"jbo")
7171 else if(Ptr->
Command ==
"fsp")
7176 else if(Ptr->
Command ==
"rsp")
7181 else if(Ptr->
Command ==
"cdt")
7187 RetStr = RetStr +
'\n' + PartStr;
7204 RetStr =
"Timetable finished";
7208 RetStr =
"No timetable";
7365 bool ForwardHeadCode;
7369 ForwardHeadCode =
true;
7374 ForwardHeadCode =
false;
7517 if(ColourNumber == 0)
7521 else if(ColourNumber == 1)
7525 else if(ColourNumber == 2)
7529 else if(ColourNumber == 3)
7533 else if(ColourNumber == 4)
7537 else if(ColourNumber == 5)
7541 else if(ColourNumber == 6)
7545 else if(ColourNumber == 7)
7549 else if(ColourNumber == 8)
7553 else if(ColourNumber == 9)
7557 else if(ColourNumber == 10)
7561 else if(ColourNumber == 11)
7565 else if(ColourNumber == 12)
7569 else if(ColourNumber == 13)
7573 else if(ColourNumber == 14)
7585 for(
int x = 0; x < 4; x++)
7592 for(
int x = 0; x < 4; x++)
7677 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
7680 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
7681 bool GiveMessagesFalse =
false;
7682 bool CheckLocationsExistInRailwayTrue =
true;
7689 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
7692 if(Marker[6] ==
'1')
8157 bool HideFlashingTrain =
true;
8160 Graphics::TBitmap *SmallTrainBitmap;
8201 HideFlashingTrain =
false;
8206 HideFlashingTrain =
false;
8211 HideFlashingTrain =
false;
8216 HideFlashingTrain =
false;
8221 HideFlashingTrain =
false;
8225 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8229 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
8253 for(
int y = 0; y < 3; y++)
8257 bool FoundFlag =
false;
8268 if(IMPair.first != IMPair.second)
8295 if((LocationName ==
"") && (
MidElement > -1))
8299 if((LocationName ==
"") && (
LagElement > -1))
8303 if(LocationName ==
"")
8305 throw Exception(
"Error - Location name not set in TrainAtLocation");
8316 for(
int x = 0; x < 4; x++)
8328 for(
int x = 0; x < 4; x++)
8345 AnsiString(LinkNumber) +
"," +
HeadCode);
8396 int DistanceToRedSignal = 0;
8397 float TimeToAct = 0;
8398 float MinsEarly = 0;
8399 TDateTime DepartureTime;
8400 TDateTime ArrivalTime;
8446 float CurrentStopTime;
8447 float LaterStopTime;
8448 float RecoverableTime;
8453 if(DistanceToRedSignal == -1)
8472 float TimeToSubtract, TotalStopTime;
8475 TimeToSubtract = RecoverableTime;
8519 if(CurrentStopTime > 0)
8521 TotalStopTime = CurrentStopTime + LaterStopTime;
8530 else if((MinsEarly > 0) && !
Stopped())
8532 TotalStopTime = LaterStopTime + MinsEarly;
8536 if(LaterStopTime == 0)
8538 TotalStopTime = CurrentStopTime;
8544 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
8547 if(AvTrackSpeed < 30)
8551 int Speed = AvTrackSpeed;
8561 TimeToAct = TotalStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
8583 if((NextEntryPos == 0) || (NextEntryPos == 2))
8708 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8751 int IncrementalMinutes = 0;
8752 int IncrementalDigits = 0;
8760 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
8789 if(AVEntry0.
Command ==
"Snt-sh")
8794 int IncrementalMinutes = 0;
8795 int IncrementalDigits = 0;
8803 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
8835 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
8895 AnsiString Loc =
"";
8896 bool ElementFound =
false;
8901 ElementFound =
true;
8906 ElementFound =
true;
8911 ElementFound =
true;
8940 else if(AVEntryPtr->
Command ==
"Fer")
8942 bool CorrectExit =
false;
9050 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9065 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9080 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9091 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
9092 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
9093 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
9095 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
9096 "," + AnsiString(Mass) +
"," + ModeStr);
9098 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr +
"," + HeadCode);
9100 int RearExitPos = -1;
9102 for(
int x = 0; x < 4; x++)
9109 if(RearExitPos == -1)
9111 throw Exception(
"Error, RearExit == -1 in AddTrain");
9113 bool ReportFlag =
true;
9130 if(ModeStr ==
"Timetable")
9136 if(MaxRunningSpeed < 10)
9138 MaxRunningSpeed = 10;
9140 if(SignallerSpeed < 10)
9142 SignallerSpeed = 10;
9144 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
9145 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
9150 if(SignallerControl)
9180 if(!SignallerControl)
9195 if(!SignallerControl)
9206 AnsiString Loc =
"";
9223 if(!SignallerControl)
9242 int RouteNumber = -1;
9243 bool SignalsSet =
false;
9250 int RouteStartPosition;
9254 if(FirstPair.first == RouteNumber)
9256 RouteStartPosition = FirstPair.second;
9258 else if(SecondPair.first == RouteNumber)
9260 RouteStartPosition = SecondPair.second;
9264 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
9270 else if(RouteNumber > -1)
9290 int LinkedRouteNumber = -1;
9311 int RouteStartPosition;
9315 if(FirstPair.first == RouteNumber)
9317 RouteStartPosition = FirstPair.second;
9319 else if(SecondPair.first == RouteNumber)
9321 RouteStartPosition = SecondPair.second;
9325 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
9331 else if(RouteNumber > -1)
9351 int LinkedRouteNumber = -1;
9372 AnsiString(TrackVectorNumber));
9375 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9384 throw Exception(
"Error, VecPos not set in EntryPos");
9386 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
9391 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
9396 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
9410 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9418 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
9428 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9458 AnsiString RetStr =
"", PartStr =
"";
9466 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
9474 if(Ptr->SignallerControl)
9476 RetStr =
"Train under signaller control";
9481 if(Ptr->ArrivalTime == Ptr->DepartureTime)
9492 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
9496 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
9500 else if(Ptr->FormatType ==
PassTime)
9504 else if(Ptr->Command ==
"Fns")
9510 else if(Ptr->Command ==
"F-nshs")
9513 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
9520 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9527 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9530 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
9533 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
9540 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
9542 PartStr =
"Terminate at " + Ptr->LocationName;
9544 else if(Ptr->Command ==
"Frh")
9546 PartStr =
"Terminate at " + Ptr->LocationName;
9548 else if(Ptr->Command ==
"Fer")
9550 AnsiString AllowedExits;
9554 else if(Ptr->Command ==
"Fjo")
9557 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9559 else if(Ptr->Command ==
"jbo")
9562 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
9564 else if(Ptr->Command ==
"fsp")
9569 else if(Ptr->Command ==
"rsp")
9574 else if(Ptr->Command ==
"cdt")
9580 RetStr = RetStr +
'\n' + PartStr;
9588 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
9601 + AnsiString(RptNum) +
",ControllerCheckNewServiceDepartureTime," + TDEPtr->
HeadCode);
9602 AnsiString DepTime =
"", EventTime =
"";
9603 bool CDTFlag =
false;
9607 if(AVI->Command ==
"cdt")
9612 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
9615 RetStr +=
"\nNew service splits at " + EventTime;
9619 if(AVI->Command ==
"jbo")
9622 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
9626 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
9631 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
9635 RetStr +=
"\nNew service departs at " + DepTime;
9795 ActiveTrackElementNameMapEntry.second = 0;
9801 std::ifstream TTBLFile(FileName, std::ios_base::binary);
9804 if(TTBLFile.is_open())
9806 char *TrainTimetableString =
new char[10000];
9808 bool EndOfFile =
false;
9811 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9813 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9820 delete[] TrainTimetableString;
9824 AnsiString OneLine(TrainTimetableString);
9825 bool FinalCallFalse =
false;
9826 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9830 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9831 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9836 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
9838 delete[] TrainTimetableString;
9842 OneLine = AnsiString(TrainTimetableString);
9848 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
9850 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
9860 OneLine = AnsiString(TrainTimetableString);
9862 if(OneLine.Length() > 9999)
9864 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
9866 delete[] TrainTimetableString;
9870 bool FinalCallFalse =
false;
9871 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
9875 delete[] TrainTimetableString;
9879 if(EndOfFile && (Count < 2))
9882 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
9884 delete[] TrainTimetableString;
9890 delete[] TrainTimetableString;
9895 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
9906 bool CheckLocationsExistInRailway)
10031 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
10041 if(OneLine[1] !=
'*')
10043 int SCPos = OneLine.Pos(
';');
10054 bool AllCommas =
true;
10056 for(
int x = 1; x < OneLine.Length() + 1; x++)
10058 if(OneLine[x] !=
',')
10063 if(AllCommas || (OneLine ==
""))
10078 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
10079 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
10080 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
10081 TDateTime StartTime(0);
10083 bool Warning =
false;
10110 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
10111 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
10112 double MaxBrakeRate = 0;
10113 double PowerAtRail = 0;
10114 int SignallerSpeed = 0;
10115 if(OneLine[1] ==
'*')
10121 int Pos = OneLine.Pos(
',');
10124 int SubStringLength = 20;
10125 if(OneLine.Length() < 20)
10127 SubStringLength = OneLine.Length();
10129 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
10133 TrainInfoStr = OneLine.SubString(1, Pos - 1);
10134 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
10144 TempTrainDataEntry.
HeadCode = HeadCode;
10148 TempTrainDataEntry.
Mass = Mass;
10156 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
10159 while(NewRemainder[NewRemainder.Length()] ==
',')
10161 if(NewRemainder.Length() > 1)
10163 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
10172 if(NewRemainder ==
"")
10174 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
10179 int CommaCount = 0;
10180 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
10182 if(NewRemainder[x] ==
',')
10187 if(CommaCount == 0)
10189 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
10191 int SubStringLength = 20;
10192 if(OneLine.Length() < 20)
10194 SubStringLength = OneLine.Length();
10197 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
10198 OneLine.SubString(1, SubStringLength) +
"'....");
10203 AnsiString OneEntry =
"";
10208 bool FinishFlag =
false;
10209 for(
int x = 0; x < CommaCount + 1; x++)
10211 if((CommaCount == 0) || (x < CommaCount))
10216 if(CommaCount == 0)
10218 OneEntry = NewRemainder;
10223 Pos = NewRemainder.Pos(
',');
10224 OneEntry = NewRemainder.SubString(1, Pos - 1);
10225 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
10231 RearStartOrRepeatMins = 0;
10232 FrontStartOrRepeatDigits = 0;
10233 NumberOfRepeats = 0;
10234 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10235 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10237 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10242 if(Warning && (Second ==
"Frh"))
10244 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
10248 if(Warning && (Second ==
"Fjo"))
10251 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
10257 if(SequenceType !=
Start)
10259 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
10263 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
10265 if(NewRemainder[1] !=
'R')
10268 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
10274 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10278 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
10281 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
10287 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
10292 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10297 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
10300 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
10307 if(SequenceType ==
Finish)
10316 TDateTime TempTime;
10322 ActionVectorEntry.
Warning = Warning;
10338 ActionVectorEntry.
Command = Second;
10353 else if(FormatType ==
TimeCmd)
10359 ActionVectorEntry.
Command = Second;
10367 ActionVectorEntry.
Command = Second;
10368 ActionVectorEntry.
ExitList = ExitList;
10376 ActionVectorEntry.
Command = Second;
10390 ActionVectorEntry.
Command = Second;
10401 ActionVectorEntry.
Command = Second;
10411 ActionVectorEntry.
Command = Second;
10420 ActionVectorEntry.
Command = Second;
10429 ActionVectorEntry.
Command = Second;
10435 ActionVectorEntry.
Command = Second;
10437 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10442 OneEntry = NewRemainder;
10447 RearStartOrRepeatMins = 0;
10448 FrontStartOrRepeatDigits = 0;
10449 NumberOfRepeats = 0;
10450 if((FinishFlag) && (OneEntry[1] !=
'R'))
10453 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
10457 if(OneEntry[1] !=
'R')
10459 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
10460 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
10462 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
10466 if(SequenceType !=
Finish)
10468 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
10475 TDateTime TempTime;
10481 ActionVectorEntry.
Warning = Warning;
10488 ActionVectorEntry.
Command = Second;
10496 ActionVectorEntry.
Command = Second;
10505 ActionVectorEntry.
Command = Second;
10514 ActionVectorEntry.
Command = Second;
10524 ActionVectorEntry.
Command = Second;
10525 ActionVectorEntry.
ExitList = ExitList;
10529 ActionVectorEntry.
Command = Second;
10531 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10536 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
10552 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
10571 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
10576 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
10591 if(TimeStr.Length() < 5)
10596 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
10601 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
10606 if(TimeStr[3] !=
':')
10611 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
10616 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
10621 while(TimeStr.Length() > 5)
10623 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
10625 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
10626 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
10628 if((WholeHours + FracHour) >= 95.98334)
10633 Time = TDateTime((WholeHours + FracHour) / 24);
10640 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
10641 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
10650 TDateTime TempTime;
10652 if(OneEntry.Length() > 0)
10654 if(OneEntry[1] ==
'W')
10657 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
10661 if(OneEntry ==
"Frh")
10671 if(OneEntry.Length() < 7)
10676 int Pos = OneEntry.Pos(
';');
10684 First = OneEntry.SubString(1, 5);
10690 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
10692 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
10695 if(Remainder.Length() < 7)
10700 Pos = Remainder.Pos(
';');
10707 Second = Remainder.SubString(1, 5);
10713 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10726 Pos = Remainder.Pos(
';');
10729 Second = Remainder;
10730 if(Second ==
"cdt")
10755 if((Pos != 4) && (Pos != 7) && (Pos != 8))
10761 Second = Remainder.SubString(1, Pos - 1);
10763 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10765 Pos = Remainder.Pos(
';');
10772 Third = Remainder.SubString(1, Pos - 1);
10773 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
10775 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
10778 int SpacePos = Third.Pos(
' ');
10784 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
10785 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
10787 if(CheckLocationsExistInRailway)
10797 if(Second ==
"Snt")
10800 SequenceType =
Start;
10809 SequenceType =
Start;
10820 if(Second ==
"Sns-sh")
10824 SequenceType =
Start;
10839 if(Second ==
"F-nshs")
10853 if(Second ==
"Sns-fsh")
10857 SequenceType =
Start;
10867 if(Second ==
"Fns-sh")
10887 if(Second ==
"pas")
10902 if(Second ==
"Fer")
10909 if(CheckLocationsExistInRailway)
10921 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
10922 (Second !=
"Frh-sh"))
10934 if(Second ==
"Frh-sh")
10942 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
10946 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
10950 if((Second ==
"Sfs") || (Second ==
"Sns"))
10952 SequenceType =
Start;
10970 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
10975 for(
int x = 1; x < LocStr.Length() + 1; x++)
10977 if(LocStr[x] <
' ')
10982 if(LocStr[x] >
'z')
10989 if(CheckLocationsExistInRailway)
10994 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
10995 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
10996 "that includes a continuation will not be valid.");
11014 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
11017 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
11022 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
11024 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
11026 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
11032 for(
int x = 3; x >= 0; x--)
11034 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
11035 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
11037 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
11053 AnsiString CurrentID =
"";
11055 if(IDSet.Length() == 0)
11057 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
11061 for(
int x = 1; x <= IDSet.Length(); x++)
11064 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
11066 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
11071 int Pos = IDSet.Pos(
' ');
11082 CurrentID = IDSet.SubString(1, Pos - 1);
11083 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
11095 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
11102 if(!ExitList.empty())
11106 if(*ELIT == VecPos)
11108 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
11115 ExitList.push_back(VecPos);
11125 Pos = IDSet.Pos(
' ');
11132 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
11139 AnsiString Remainder =
"";
11140 int SemiColonCount = 0;
11142 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
11144 if(TrainInfoStr[x] ==
';')
11149 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
11151 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
11152 "'. Should be headcode + optional description for a continuing service;" +
11153 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
11157 if(SemiColonCount == 0)
11159 HeadCode = TrainInfoStr;
11168 if(SemiColonCount == 1)
11170 Pos = TrainInfoStr.Pos(
';');
11171 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11172 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11178 if(Description ==
"")
11180 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11184 if(Description.Length() > 60)
11186 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11190 for(
int x = 1; x < Description.Length() + 1; x++)
11192 if((Description[x] <
' ') || (Description[x] >
'~'))
11194 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11203 Pos = TrainInfoStr.Pos(
';');
11204 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
11205 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
11211 Pos = Remainder.Pos(
';');
11212 Description = Remainder.SubString(1, Pos - 1);
11213 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11214 if(Description ==
"")
11216 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
11220 if(Description.Length() > 60)
11222 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
11226 for(
int x = 1; x < Description.Length() + 1; x++)
11228 if((Description[x] <
' ') || (Description[x] > 126))
11230 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
11235 Pos = Remainder.Pos(
';');
11236 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
11238 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11239 if(StartSpeedStr ==
"")
11241 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
11245 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
11247 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
11249 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
11254 StartSpeed = StartSpeedStr.ToInt();
11260 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11264 Pos = Remainder.Pos(
';');
11265 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
11267 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11268 if(MaxRunningSpeedStr ==
"")
11270 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
11274 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
11276 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
11278 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
11283 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
11289 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11293 if(MaxRunningSpeed < 10)
11296 MaxRunningSpeed = 10;
11299 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11303 Pos = Remainder.Pos(
';');
11304 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
11306 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11309 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
11313 for(
int x = 1; x < MassStr.Length() + 1; x++)
11315 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
11317 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
11322 Mass = MassStr.ToInt() * 1000;
11328 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
11334 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
11338 Pos = Remainder.Pos(
';');
11339 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
11341 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11342 if(MaxBrakeForceStr ==
"")
11344 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
11348 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
11350 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
11352 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
11357 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
11360 if((MaxBrakeForce / Mass) > 1)
11362 MaxBrakeForce = Mass;
11365 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
11369 if((MaxBrakeForce / Mass) < 0.01)
11371 MaxBrakeForce = Mass * 0.01;
11374 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
11379 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
11381 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
11383 if(SemiColonCount == 6)
11385 GrossPowerStr = Remainder;
11386 SignallerSpeedStr =
"30";
11390 Pos = Remainder.Pos(
';');
11391 GrossPowerStr = Remainder.SubString(1, Pos - 1);
11392 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11395 if(GrossPowerStr ==
"")
11397 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
11401 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
11403 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
11405 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
11411 double GrossPower = GrossPowerStr.ToInt() * 1000;
11418 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
11422 else if(GrossPower == 0)
11427 else if((GrossPower > 0) && (GrossPower < 10000))
11430 GrossPower = 10000;
11432 PowerAtRail = GrossPower * 0.8;
11436 if(SignallerSpeedStr ==
"")
11438 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
11442 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
11444 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
11446 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
11451 SignallerSpeed = SignallerSpeedStr.ToInt();
11457 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
11461 if(SignallerSpeed < 10)
11464 SignallerSpeed = 10;
11467 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
11485 if(OneEntry.Length() < 7)
11487 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11491 int SemiColonCount = 0;
11493 for(
int x = 1; x < OneEntry.Length() + 1; x++)
11495 if(OneEntry[x] ==
';')
11500 if(SemiColonCount != 3)
11502 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11506 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
11508 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
11512 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
11517 Pos = Remainder.Pos(
';');
11518 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
11520 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11521 if(MinutesStr ==
"")
11523 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
11527 if(MinutesStr.Length() > 3)
11530 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
11534 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
11536 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
11538 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
11543 RearStartOrRepeatMins = MinutesStr.ToInt();
11544 if(RearStartOrRepeatMins == 0)
11546 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
11550 Pos = Remainder.Pos(
';');
11551 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
11553 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11554 if(DigitsStr ==
"")
11556 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
11560 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
11562 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
11564 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
11569 if(DigitsStr.Length() > 2)
11571 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
11575 FrontStartOrRepeatDigits = DigitsStr.ToInt();
11589 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
11593 AnsiString NumberStr = Remainder;
11595 if(NumberStr ==
"")
11597 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
11601 if(NumberStr.Length() > 4)
11604 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
11608 for(
int x = 1; x < NumberStr.Length() + 1; x++)
11610 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
11613 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
11618 NumberOfRepeats = NumberStr.ToInt();
11619 if(NumberOfRepeats == 0)
11621 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
11777 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
11796 TwoLocationFlag =
false;
11802 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
11816 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
11832 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
11844 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
11871 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
11882 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11887 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
11897 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11902 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
11912 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11923 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
11933 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
11945 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
11952 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
11961 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
11981 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
11983 AnsiString LocationName =
"";
11999 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
12000 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12009 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
12018 if(AVEntry0.
Command ==
"Snt-sh")
12032 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
12048 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
12049 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12060 bool FoundFlag =
false;
12066 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12078 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
12091 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12100 ": an event should have had a location name associated with it but it could not be found");
12106 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
12128 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12138 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
12145 if(AVEntry.
Command ==
"F-nshs")
12150 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
12178 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
12179 ". The event isn't valid for a stationary train.");
12189 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
12197 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
12198 ". The event isn't valid for a stationary train.");
12216 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
12217 ". The event isn't valid for a stationary train.");
12227 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
12235 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
12236 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
12254 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
12255 ". The event isn't valid for a moving train.");
12277 bool LastEntryIsAnArrival =
false;
12284 LastEntryIsAnArrival =
false;
12285 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12292 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12294 if(LastEntryIsAnArrival)
12298 LastEntryIsAnArrival =
false;
12304 LastEntryIsAnArrival =
true;
12311 LastEntryIsAnArrival =
true;
12312 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12319 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
12321 if(LastEntryIsAnArrival)
12325 LastEntryIsAnArrival =
false;
12331 LastEntryIsAnArrival =
true;
12341 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12349 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
12357 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
12358 ". The event isn't valid for a stationary train.");
12369 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
12377 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
12378 ". The event isn't valid for a moving train.");
12392 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12399 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12403 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
12410 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
12414 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
12423 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
12427 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
12434 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
12445 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12460 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
12468 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
12483 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12495 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
12507 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
12508 ", may be before timetable start time");
12519 AnsiString LastLocationName =
"";
12523 bool LastEntryIsAnArrival =
false;
12528 LastEntryIsAnArrival =
false;
12529 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12530 if(LastLocationName !=
"")
12532 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
12534 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
12547 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12559 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12572 TwoLocationFlag =
true;
12579 LastEntryIsAnArrival =
false;
12583 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
12586 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
12591 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
12594 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
12600 LastEntryIsAnArrival = !LastEntryIsAnArrival;
12606 LastEntryIsAnArrival =
true;
12607 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
12608 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12620 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12632 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
12645 TwoLocationFlag =
true;
12650 LastEntryIsAnArrival =
false;
12654 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
12657 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
12665 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
12672 LastEntryIsAnArrival = !LastEntryIsAnArrival;
12680 AnsiString LocationNameToBeChecked =
"";
12685 unsigned int y = 0;
12700 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
12701 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
12719 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
12728 TwoLocationFlag =
true;
12744 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12749 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
12751 AnsiString LocName =
"";
12757 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
12764 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
12787 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12812 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12834 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12856 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12875 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12878 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
12893 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12898 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
12902 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
12906 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
12910 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
12949 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12951 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
12957 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
12970 int IncMinutes = 0;
12980 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12986 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
12992 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
12997 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13003 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
13008 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13021 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13047 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
13055 if(HeadCode.Length() > 4)
13057 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
13068 int ForwardCount = 0;
13069 int ReverseCount = 0;
13071 if(MainHeadCode == SecondHeadCode)
13073 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
13082 if(TDEntry.
HeadCode == MainHeadCode)
13084 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13099 if(ForwardCount == 0)
13102 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
13104 if(ForwardCount > 2)
13107 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
13108 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13117 if(TDEntry.
HeadCode == SecondHeadCode)
13119 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13134 if(ReverseCount == 0)
13136 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
13141 if(ReverseCount > 2)
13144 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
13145 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
13150 if(ForwardCount != ReverseCount)
13152 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
13153 " than the other way round");
13184 int ForwardCount = 0;
13185 int ReverseCount = 0;
13186 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
13195 if(TDEntry.
HeadCode == MainHeadCode)
13197 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13200 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13205 ForwardEntryPtr = &AVEntry;
13207 ForwardTDVectorNumber = x;
13210 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
13211 (AVEntry.
Command ==
"Frh-sh")))
13216 ForwardEntryPtr = &AVEntry;
13218 ForwardTDVectorNumber = x;
13224 if(ForwardCount == 0)
13227 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
13229 if(ForwardCount > 1)
13231 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
13241 if(TDEntry.
HeadCode == OtherHeadCode)
13243 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13246 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
13252 ReverseEntryPtr = &AVEntry;
13253 ReverseTDVectorNumber = x;
13256 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
13262 ReverseEntryPtr = &AVEntry;
13263 ReverseTDVectorNumber = x;
13270 if(ReverseCount == 0)
13272 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
13277 if(ReverseCount > 1)
13279 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
13286 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
13287 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
13288 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
13289 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
13293 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
13300 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
13305 if(ForwardEntryPtr->LocationName ==
"")
13307 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13308 ". One or other service does not have a location set");
13315 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
13316 ". One or other service does not have a location set");
13321 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
13323 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13324 " is at a different location to the referencing train " + MainHeadCode);
13332 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
13334 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
13335 " has a different event time to the referencing train " + MainHeadCode);
13343 if(ForwardShuttleStart && ReverseShuttleFinish)
13348 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
13349 " first repeat restart time not consistent with finish service " + OtherHeadCode);
13355 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
13358 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13360 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
13361 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13367 if(ReverseEntryPtr->
Command ==
"Fjo")
13370 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13372 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
13373 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13379 if(ReverseEntryPtr->
Command ==
"Fns")
13382 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
13384 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
13385 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
13391 if(ForwardEntryPtr->Command ==
"Sfs")
13393 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
13396 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
13403 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
13405 if(ReverseEntryPtr->
Command !=
"Sfs")
13407 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
13417 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
13424 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
13431 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
13436 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13447 if(ForwardEntryPtr->Command ==
"Sns")
13449 if(ReverseEntryPtr->
Command !=
"Fns")
13451 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
13452 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
13458 if(ForwardEntryPtr->Command ==
"Fns")
13460 if(ReverseEntryPtr->
Command !=
"Sns")
13462 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
13463 " and forms a new service with headcode " + OtherHeadCode);
13470 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13481 if(ForwardEntryPtr->Command ==
"jbo")
13483 if(ReverseEntryPtr->
Command !=
"Fjo")
13485 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
13486 " and is joined by a train with headcode " + OtherHeadCode);
13492 if(ForwardEntryPtr->Command ==
"Fjo")
13494 if(ReverseEntryPtr->
Command !=
"jbo")
13496 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
13497 " and joins a train with headcode " + OtherHeadCode);
13504 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13514 if(ForwardShuttleStart)
13517 if(!ReverseShuttleFinish)
13520 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
13521 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
13527 if(ReverseShuttleStart)
13530 if(!ForwardShuttleFinish)
13533 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
13534 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
13541 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
13553 bool MainRepeat =
false, OtherRepeat =
false;
13563 OtherRepeat =
true;
13566 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
13568 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
13569 " and the associated train with headcode " + OtherHeadCode);
13574 if(MainRepeat && OtherRepeat)
13580 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
13581 " and the associated train with headcode " + OtherHeadCode);
13603 while(Input[1] ==
' ')
13605 if(Input.Length() > 1)
13607 Input = Input.SubString(2, Input.Length() - 1);
13621 while(Input[Input.Length()] ==
' ')
13623 if(Input.Length() > 1)
13625 Input = Input.SubString(1, Input.Length() - 1);
13635 AnsiString Output =
"";
13636 bool DelimiterFound =
false;
13638 for(
int x = 1; x < Input.Length() + 1; x++)
13642 if(Input[x] ==
' ')
13647 if((Input[x] !=
',') && (Input[x] !=
';'))
13649 DelimiterFound =
false;
13650 Output = Output + Input[x];
13654 DelimiterFound =
true;
13655 Output = Output + Input[x];
13667 DelimiterFound =
false;
13668 for(
int x = Input.Length(); x > 0; x--)
13672 if(Input[x] ==
' ')
13677 if((Input[x] !=
',') && (Input[x] !=
';'))
13679 DelimiterFound =
false;
13680 Output = AnsiString(Input[x]) + Output;
13684 DelimiterFound =
true;
13685 Output = AnsiString(Input[x]) + Output;
13705 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
13707 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
13719 LocationName = LocRear;
13723 LocationName = LocFront;
13725 if(LocationName ==
"")
13751 AnsiString TimeLocLocationName;
13752 bool FoundFlag =
false;
13754 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
13769 if(TimeLocLocationName == LocationName)
13786 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
13789 if(RearPosition < 0)
13796 if(FrontPosition < 0)
13807 for(
int x = 0; x < 4; x++)
13809 if(RearTrackElement.
Conn[x] == FrontPosition)
13824 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
13831 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
13837 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
13842 if((RearType ==
Points) && (RearExitPos == 3))
13844 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
13850 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
13865 AnsiString(RearExitPos));
13876 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
13878 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
13881 AnsiString RearName, FrontName;
13897 FrontName = FrontTrackElement.
ElementID;
13900 int LockedVectorNumber;
14070 "," + AnsiString(IncDigits));
14073 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
14078 return(BaseHeadCode);
14080 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
14081 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
14083 while(NextRepeatDigits >= 100)
14085 NextRepeatDigits -= 100;
14087 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
14089 if(NextRepeatDigitsStr.Length() < 2)
14091 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
14093 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
14096 return(NextRepeatHeadCode);
14104 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
14105 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
14108 return(NextRepeatTime);
14117 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
14118 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14119 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14120 int RepeatSecs = RepeatMinutes * 60;
14122 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
14140 NonRepeatingHeadCode);
14141 int ForwardCount = 0;
14142 int ReverseCount = 0;
14143 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14153 if(TDEntry.
HeadCode == MainHeadCode)
14155 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14161 ForwardEntryPtr = &AVEntry;
14163 ForwardTDVectorNumber = x;
14168 if(ForwardCount == 0)
14171 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
14173 if(ForwardCount > 1)
14175 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
14185 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
14187 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14194 ReverseEntryPtr = &AVEntry;
14195 ReverseTDVectorNumber = x;
14201 if(ReverseCount == 0)
14203 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
14208 if(ReverseCount > 1)
14210 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14211 NonRepeatingHeadCode);
14216 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
14218 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
14223 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
14225 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
14230 if(ForwardEntryPtr->LocationName ==
"")
14232 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14233 ". One or other service does not have a location set");
14240 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
14241 ". One or other service does not have a location set");
14246 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14248 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
14249 " is at a different location to the referencing train " + MainHeadCode);
14254 if(ForwardEntryPtr->Command ==
"F-nshs")
14257 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14259 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
14260 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
14266 if(ForwardEntryPtr->Command ==
"Fns-sh")
14270 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
14272 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
14273 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
14279 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
14282 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14284 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
14285 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
14303 if(ForwardEntryPtr->Command ==
"Sns-sh")
14305 if(ReverseEntryPtr->
Command !=
"F-nshs")
14307 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
14308 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
14314 if(ForwardEntryPtr->Command ==
"F-nshs")
14316 if(ReverseEntryPtr->
Command !=
"Sns-sh")
14318 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
14319 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
14326 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14337 if(ForwardEntryPtr->Command ==
"Sns-fsh")
14339 if(ReverseEntryPtr->
Command !=
"Fns-sh")
14342 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
14343 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
14349 if(ForwardEntryPtr->Command ==
"Fns-sh")
14351 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
14354 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
14355 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
14362 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
14386 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
14387 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
14388 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
14389 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
14391 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
14415 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
14418 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
14419 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14421 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14423 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14428 while(LastActionCommand ==
"Fns")
14430 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
14431 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
14432 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
14435 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
14436 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
14443 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
14446 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
14447 ". The linking of two or more shuttles is not permitted.");
14467 ShowMessage(Message);
14485 ShowMessage(Message);
14524 AnsiString(ActionEventType) +
"," + LocationID);
14525 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
14530 Prefix =
" ERROR: ";
14533 Prefix =
" HELD: ";
14534 ErrorLog =
" can't enter railway, train obstructing entry position ";
14535 WarningStr =
" can't enter railway, train obstructing entry position ";
14540 Prefix =
" HELD: ";
14541 ErrorLog =
" can't enter railway, route set against it at entry position ";
14542 WarningStr =
" can't enter railway, route set against it at entry position ";
14547 Prefix =
" HELD: ";
14548 ErrorLog =
" can't be created, train obstructing ";
14549 WarningStr =
" can't be created, train obstructing ";
14554 Prefix =
" HELD: ";
14555 ErrorLog =
" can't be created on a locked route at ";
14556 WarningStr =
" can't be created on a locked route at ";
14561 Prefix =
" HELD: ";
14562 ErrorLog =
" can't enter on a locked route at ";
14563 WarningStr =
" can't enter on a locked route at ";
14568 Prefix =
" HELD: ";
14569 ErrorLog =
" can't be created, diverging points at ";
14570 WarningStr =
" can't be created, diverging points at ";
14575 ErrorLog =
" left railway unexpectedly at ";
14580 ErrorLog =
" left railway at an incorrect exit at ";
14585 ErrorLog =
" failed to split - location too short at ";
14586 WarningStr =
" failed to split, location too short at ";
14591 Prefix =
" HELD: ";
14592 ErrorLog =
" unable to split - other train obstructing at ";
14593 WarningStr =
" unable to split - other train obstructing at ";
14598 ErrorLog =
" stopped at buffers unexpectedly at position ";
14602 ErrorLog =
" failed to stop at ";
14607 ErrorLog =
" failed to split at ";
14612 ErrorLog =
" failed to be joined by other train at ";
14617 ErrorLog =
" failed to join other train at ";
14622 ErrorLog =
" failed to terminate at ";
14627 ErrorLog =
" failed to form new service at ";
14632 ErrorLog =
" failed to exit railway ";
14637 ErrorLog =
" failed to change direction at ";
14642 ErrorLog =
" failed to pass ";
14647 ErrorLog =
" facing buffers and unable to start at ";
14651 ErrorLog =
" DERAILED at position ";
14652 Prefix =
" DERAILMENT: ";
14657 ErrorLog =
" CRASHED INTO BUFFERS at ";
14658 Prefix =
" CRASH: ";
14663 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
14664 Prefix =
" CRASH: ";
14669 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
14670 Prefix =
" CRASH: ";
14674 else if(ActionEventType ==
FailSPAD)
14676 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
14677 Prefix =
" SPAD: ";
14682 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
14683 Prefix =
" SPAD RISK: ";
14688 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
14692 Prefix =
" WARNING: ";
14693 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
14694 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
14699 Prefix =
" WARNING: ";
14700 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
14701 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
14739 std::ofstream OutFile(
"TrainData.csv");
14743 ShowMessage(
"Output file TrainData.csv failed to open");
14750 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
14755 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
14756 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
14757 "RepeatNumber" <<
'\n' <<
'\n';
14758 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14761 AnsiString TimetableEntryTypeStr;
14767 TimetableEntryTypeStr =
"NoFormat";
14773 TimetableEntryTypeStr =
"TimeLoc";
14779 TimetableEntryTypeStr =
"TimeTimeLoc";
14785 TimetableEntryTypeStr =
"TimeCmd";
14791 TimetableEntryTypeStr =
"StartNew";
14797 TimetableEntryTypeStr =
"TimeCmdHeadCode";
14803 TimetableEntryTypeStr =
"FinRemHere";
14809 TimetableEntryTypeStr =
"FNSShuttle";
14815 TimetableEntryTypeStr =
"SNTShuttle";
14821 TimetableEntryTypeStr =
"SNSShuttle";
14827 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
14833 TimetableEntryTypeStr =
"FSHNewService";
14839 TimetableEntryTypeStr =
"Repeat";
14845 TimetableEntryTypeStr =
"Default";
14856 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
14857 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
14860 AnsiString RunningEntryStr;
14866 RunningEntryStr =
"NotStarted";
14872 RunningEntryStr =
"Running";
14878 RunningEntryStr =
"Exited";
14882 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
14899 ShowMessage(Message);
14900 BaseTime = TDateTime::CurrentDateTime();
14914 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
14927 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14929 for(
int x = 0; x < NumberOfTrains; x++)
14931 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
14951 int NumberOfTrains;
14958 for(
int x = 0; x < NumberOfTrains; x++)
14995 for(
int x = 0; x < LockedRouteVectorSize; x++)
15002 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
15013 int LockedRouteVectorSize;
15020 for(
int x = 0; x < LockedRouteVectorSize; x++)
15078 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15086 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
15097 int ContinuationAutoSigVectorSize;
15104 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
15174 if(AVFirstEntry.
Command ==
"Snt")
15198 CTEMMP.second = CTEEntry;
15205 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
15213 CTEMMP.second = CTEEntry;
15234 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15251 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
15253 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
15264 AnsiString RetStr =
"", PartStr =
"";
15379 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15383 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
15385 AnsiString ShortTTName =
"";
15387 for(
int x = TTFileName.Length(); x > 0; x--)
15389 if(TTFileName[x] ==
'\\')
15391 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
15396 ShowMessage(
"Creates two timetables named " + ShortTTName +
15397 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
15399 Screen->Cursor = TCursor(-11);
15401 AnsiString FormatNoDPStr =
"#######0";
15402 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
15405 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
15412 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
15414 if(TrainDataEntry.
Mass > 0)
15416 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
15420 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
15424 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
15428 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
15430 FirstHeadCode = TrainDataEntry.
HeadCode;
15431 int IncDigits = 0, IncMinutes = 0;
15433 if(!ActionVector.empty())
15435 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
15437 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
15438 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
15446 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
15448 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
15456 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15461 AnsiString PartStr =
"", TimeStr =
"";
15478 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15482 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
15492 PartStr =
"Enters at " + LocName;
15505 PartStr =
"Created at " + LocName;
15519 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
15524 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
15530 else if(ActionVectorEntry.
Command ==
"Sfs")
15532 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
15536 else if(ActionVectorEntry.
Command ==
"Sns")
15538 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15546 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15552 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
15560 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
15563 AnsiString FirstHeadCode = TDE->
HeadCode;
15567 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
15579 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
15581 OneTTEntry.
Action = PartStr;
15582 OneTTEntry.
Time = TimeStr;
15584 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
15589 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
15595 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
15600 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
15608 else if(ActionVectorEntry.
Command ==
"jbo")
15610 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
15614 else if(ActionVectorEntry.
Command ==
"fsp")
15616 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
15620 else if(ActionVectorEntry.
Command ==
"rsp")
15622 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
15626 else if(ActionVectorEntry.
Command ==
"cdt")
15628 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
15634 if(ActionVectorEntry.
Command ==
"Fns")
15636 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15640 else if(ActionVectorEntry.
Command ==
"F-nshs")
15642 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15648 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
15655 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15661 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
15668 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
15673 else if(ActionVectorEntry.
Command ==
"Frh")
15675 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
15680 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
15684 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
15694 else if(ActionVectorEntry.
Command ==
"Fer")
15696 AnsiString AllowedExits;
15700 else if(ActionVectorEntry.
Command ==
"Fjo")
15702 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
15711 OneTTEntry.
Action = PartStr;
15712 OneTTEntry.
Time = TimeStr;
15719 AllTTTrains->push_back(OneTTLine);
15723 std::ofstream TTFile(TTFileName.c_str());
15727 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
15728 delete AllTTTrains;
15763 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
15764 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
15766 TTFile << AllTTTrains->at(x).Header.c_str();
15769 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
15771 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
15773 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
15777 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
15780 TTFile <<
'\n' <<
'\n';
15782 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
15784 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
15785 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
15787 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
15789 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
15793 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
15798 TTFile <<
'\n' <<
'\n';
15803 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
15805 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
15807 std::ofstream TTFile2(TTFileName2.c_str());
15811 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
15812 delete AllTTTrains;
15816 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
15817 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
15818 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
15820 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
15825 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
15826 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
15828 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
15830 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
15832 bool GiveMessagesFalse =
false;
15833 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
15834 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
15835 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
15840 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
15841 TimeString = TimeString.SubString(9, 5);
15842 ActionString +=
" " + OtherHeadCode;
15844 if(TimeString.SubString(1, 7) ==
"End at ")
15847 TimeString = TimeString.SubString(8, 5);
15849 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
15850 AnsiMultiMapEntry.first = TimeString;
15851 AnsiMultiMapEntry.second = OneLine;
15852 TAMM->insert(AnsiMultiMapEntry);
15857 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
15859 TTFile2 << (AMMIT->second).c_str();
15861 delete AllTTTrains;
15870 bool AtLocChecked,
int ArrRange,
int DepRange)
15874 bool AnalysisError =
false;
15900 TTrainDataVector::iterator TDVIt, TDVCopyIt;
15902 int IteratorNumber = 0;
15903 AnsiString AnsiSuffix =
"";
15908 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
15910 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
15913 AnsiSuffix = AnsiString(Suffix);
15914 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
15921 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
15922 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
15927 ServiceCallingLocsList.clear();
15928 if(ActionVector.empty())
15932 if(ActionVector.at(0).SignallerControl)
15936 for(
unsigned int z = 0; z < ActionVector.size(); z++)
15954 int HLoc = TE.
HLoc;
15955 int VLoc = TE.
VLoc;
15956 AnsiString HString;
15957 AnsiString VString;
15960 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
15964 HString = AnsiString(HLoc);
15968 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
15972 VString = AnsiString(VLoc);
15974 ServiceCallingLocsList.push_back(HString +
'-' + VString);
15997 else if(AVE.
Command ==
"cdt")
15999 if(ActionVector.at(z-1).SequenceType ==
Start)
16003 else if(ActionVector.at(z+1).SequenceType ==
Finish)
16010 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
16019 ServiceCallingLocsList.push_back(LName);
16023 int HLoc = TE.
HLoc;
16024 int VLoc = TE.
VLoc;
16025 AnsiString HString;
16026 AnsiString VString;
16029 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16033 HString = AnsiString(HLoc);
16037 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16041 VString = AnsiString(VLoc);
16043 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16047 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
16081 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
16087 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
16088 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
16089 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
16093 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16098 TDateTime LastTDTime;
16099 int IncMinutes = 0;
16101 if(ActionVector.empty())
16105 if(ActionVector.at(0).SignallerControl)
16109 if(AVLast->FormatType ==
Repeat)
16111 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16119 if(AVLast->ArrivalTime != TDateTime(-1))
16121 LastTDTime = AVLast->ArrivalTime;
16123 else if(AVLast->EventTime != TDateTime(-1))
16125 LastTDTime = AVLast->EventTime;
16176 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16181 int IncMinutes = 0;
16183 if(ActionVector.empty())
16187 if(ActionVector.at(0).SignallerControl)
16191 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16193 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16195 for(
int y = 0; y < NumTrains; y++)
16209 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16224 LocServiceTimesVector.push_back(TLSTEntry);
16227 AnsiString IncTime =
"", FoundStopTime =
"";
16228 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16230 if(ActionVector.at(a).FormatType ==
TimeLoc)
16235 if(ActionVector.at(a).SequenceType ==
Finish)
16241 if(FoundStopTime ==
"")
16243 throw Exception(
"Failure to determine FoundStopTime for located Snt");
16245 int WhileCount = 0;
16254 if(IncTime >= FoundStopTime)
16258 LocServiceTimesVector.push_back(TLSTEntry);
16259 if(WhileCount > 2000)
16261 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
16274 int HLoc = TE.
HLoc;
16275 int VLoc = TE.
VLoc;
16276 AnsiString HString;
16277 AnsiString VString;
16280 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16284 HString = AnsiString(HLoc);
16288 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16292 VString = AnsiString(VLoc);
16294 TLSTEntry.
Location = HString +
'-' + VString;
16298 LocServiceTimesVector.push_back(TLSTEntry);
16306 LocServiceTimesVector.push_back(TLSTEntry);
16308 AnsiString IncTime =
"", FoundStopTime =
"";
16309 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16311 if(ActionVector.at(a).FormatType ==
TimeLoc)
16316 if(ActionVector.at(a).SequenceType ==
Finish)
16322 if(FoundStopTime ==
"")
16324 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16326 int WhileCount = 0;
16335 if(IncTime >= FoundStopTime)
16339 LocServiceTimesVector.push_back(TLSTEntry);
16340 if(WhileCount > 2000)
16342 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16352 bool SkipAddingMinutes =
false;
16355 LocServiceTimesVector.push_back(TLSTEntry);
16357 AnsiString IncTime =
"", FoundStopTime =
"";
16358 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
16360 if(ActionVector.at(a).FormatType ==
TimeLoc)
16365 if(ActionVector.at(a).SequenceType ==
Finish)
16368 if((a == z + 1) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
16371 LocServiceTimesVector.pop_back();
16372 SkipAddingMinutes =
true;
16377 if(FoundStopTime ==
"")
16379 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
16381 if(!SkipAddingMinutes)
16383 int WhileCount = 0;
16392 if(IncTime >= FoundStopTime)
16396 LocServiceTimesVector.push_back(TLSTEntry);
16397 if(WhileCount > 2000)
16399 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
16408 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
16410 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
16412 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
16413 LocServiceTimesVector.pop_back();
16414 LocServiceTimesVector.push_back(TLSTEntry);
16419 LocServiceTimesVector.push_back(TLSTEntry);
16425 LocServiceTimesVector.push_back(TLSTEntry);
16444 LocServiceTimesVector.push_back(TLSTEntry);
16448 AnsiString TempDepTime = TLSTEntry.
DepTime;
16450 LocServiceTimesVector.push_back(TLSTEntry);
16452 while(TLSTEntry.
AtLocTime < TempDepTime)
16457 TLSTEntry.
DepTime = TempDepTime;
16458 LocServiceTimesVector.push_back(TLSTEntry);
16462 LocServiceTimesVector.push_back(TLSTEntry);
16473 LocServiceTimesVector.push_back(TLSTEntry);
16476 LocServiceTimesVector.push_back(TLSTEntry);
16493 AnsiString HString;
16494 AnsiString VString;
16497 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16501 HString = AnsiString(HLoc);
16505 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16509 VString = AnsiString(VLoc);
16511 TLSTEntry.
Location = HString +
'-' + VString;
16513 LocServiceTimesVector.push_back(TLSTEntry);
16518 AnsiString FrhTime;
16519 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16523 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16531 LocServiceTimesVector.push_back(TLSTEntry);
16537 LocServiceTimesVector.push_back(TLSTEntry);
16542 else if(AVE.
Command ==
"Frh-sh")
16544 if(y == NumTrains - 1)
16550 LocServiceTimesVector.push_back(TLSTEntry);
16556 LocServiceTimesVector.push_back(TLSTEntry);
16597 TLocServiceTimesVector::iterator Ptr1, Ptr2;
16600 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16601 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
16603 std::ofstream TTFile3(TTFileName3.c_str());
16607 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
16611 if(LocServiceTimesVector.empty())
16613 ShowMessage(
"No timetabled services found");
16615 DeleteFile(TTFileName3);
16619 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n\n\n";
16626 Ptr1 = LocServiceTimesVector.begin();
16628 while(Ptr2 != LocServiceTimesVector.end())
16630 while(Ptr2->Location == Ptr1->Location)
16633 if(Ptr2 == LocServiceTimesVector.end())
16640 if(Ptr2 != LocServiceTimesVector.end())
16648 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
16649 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
16650 MinuteString =
" minutes";
16651 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16654 MinuteString =
" minute";
16656 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
16657 TTFile3 <<
",Platforms,Trains\n\n";
16659 Ptr1 = LocServiceTimesVector.begin();
16661 while(Ptr2 != LocServiceTimesVector.end())
16663 PreviousService =
"";
16664 NumTrainsAtLoc = 0;
16665 ServiceAndRepeatNumTotal =
"";
16667 NumPlatsAtThisLocCalculated =
false;
16669 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
16671 PreviousService =
"";
16672 NumTrainsAtLoc = 0;
16673 ServiceAndRepeatNumTotal =
"";
16675 NumPlatsAtThisLocCalculated =
false;
16679 if(Ptr2 == LocServiceTimesVector.end())
16684 if(Ptr2 == LocServiceTimesVector.end())
16688 while(Ptr2->Location == Ptr1->Location)
16690 PreviousService =
"";
16691 NumTrainsAtLoc = 0;
16692 ServiceAndRepeatNumTotal =
"";
16693 BasicTime = Ptr1->ArrTime;
16694 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
16698 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
16700 BasicTime = Ptr2->ArrTime;
16703 if(Ptr2 == LocServiceTimesVector.end())
16707 if(Ptr2->Location != Ptr1->Location)
16712 if(Ptr2 == LocServiceTimesVector.end())
16716 if(Ptr2->Location != Ptr1->Location)
16722 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
16726 if(!NumPlatsAtThisLocCalculated)
16729 NumPlatsAtThisLocCalculated =
true;
16731 if(Ptr1->ServiceAndRepeatNum != PreviousService)
16733 if(ServiceAndRepeatNumTotal ==
"")
16735 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
16736 NumTrainsAtLoc = 1;
16740 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
16743 PreviousService = Ptr2->ServiceAndRepeatNum;
16744 if(ServiceAndRepeatNumTotal ==
"")
16746 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
16747 NumTrainsAtLoc = 1;
16751 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
16755 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
16757 int MaxNumberOfSameDirections = 0;
16758 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
16763 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
16767 AnsiString Asterisk =
"";
16768 if(MaxNumberOfSameDirections >= NumPlats)
16773 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16774 ArrivalsPrinted =
true;
16775 ServiceAndRepeatNumTotal =
"";
16777 if(Ptr2 == LocServiceTimesVector.end())
16781 if(Ptr2->Location != Ptr1->Location)
16786 if(Ptr2 == LocServiceTimesVector.end())
16792 if(!ArrivalsPrinted)
16794 TTFile3 <<
"Nothing to report for arrivals";
16796 TTFile3 <<
"\n\n\n";
16804 Ptr1 = LocServiceTimesVector.begin();
16806 while(Ptr2 != LocServiceTimesVector.end())
16808 while(Ptr2->Location == Ptr1->Location)
16811 if(Ptr2 == LocServiceTimesVector.end())
16818 if(Ptr2 != LocServiceTimesVector.end())
16825 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
16826 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
16827 MinuteString =
" minutes";
16828 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
16831 MinuteString =
" minute";
16833 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
16834 TTFile3 <<
",Platforms,Trains\n\n";
16836 Ptr1 = LocServiceTimesVector.begin();
16838 while(Ptr2 != LocServiceTimesVector.end())
16840 PreviousService =
"";
16841 NumTrainsAtLoc = 0;
16842 ServiceAndRepeatNumTotal =
"";
16844 NumPlatsAtThisLocCalculated =
false;
16846 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
16848 PreviousService =
"";
16849 NumTrainsAtLoc = 0;
16850 ServiceAndRepeatNumTotal =
"";
16852 NumPlatsAtThisLocCalculated =
false;
16856 if(Ptr2 == LocServiceTimesVector.end())
16861 if(Ptr2 == LocServiceTimesVector.end())
16865 while(Ptr2->Location == Ptr1->Location)
16867 PreviousService =
"";
16868 NumTrainsAtLoc = 0;
16869 ServiceAndRepeatNumTotal =
"";
16870 BasicTime = Ptr1->DepTime;
16871 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
16875 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
16877 BasicTime = Ptr2->DepTime;
16880 if(Ptr2 == LocServiceTimesVector.end())
16884 if(Ptr2->Location != Ptr1->Location)
16889 if(Ptr2 == LocServiceTimesVector.end())
16893 if(Ptr2->Location != Ptr1->Location)
16899 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
16903 if(!NumPlatsAtThisLocCalculated)
16906 NumPlatsAtThisLocCalculated =
true;
16908 if(Ptr1->ServiceAndRepeatNum != PreviousService)
16910 if(ServiceAndRepeatNumTotal ==
"")
16912 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
16913 NumTrainsAtLoc = 1;
16917 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
16920 PreviousService = Ptr2->ServiceAndRepeatNum;
16921 if(ServiceAndRepeatNumTotal ==
"")
16923 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
16924 NumTrainsAtLoc = 1;
16928 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
16932 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
16934 int MaxNumberOfSameDirections = 0;
16935 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
16940 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
16944 AnsiString Asterisk =
"";
16945 if(MaxNumberOfSameDirections >= NumPlats)
16950 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
16951 DeparturesPrinted =
true;
16952 ServiceAndRepeatNumTotal =
"";
16954 if(Ptr2 == LocServiceTimesVector.end())
16958 if(Ptr2->Location != Ptr1->Location)
16963 if(Ptr2 == LocServiceTimesVector.end())
16969 if(!DeparturesPrinted)
16971 TTFile3 <<
"Nothing to report for departures";
16973 TTFile3 <<
"\n\n\n";
16983 Ptr1 = LocServiceTimesVector.begin();
16985 while(Ptr2 != LocServiceTimesVector.end())
16987 while(Ptr2->Location == Ptr1->Location)
16990 if(Ptr2 == LocServiceTimesVector.end())
16997 if(Ptr2 != LocServiceTimesVector.end())
17004 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
17005 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
17006 TTFile3 <<
",Platforms,Trains,\n\n";
17007 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17008 Ptr1 = LocServiceTimesVector.begin();
17010 while(Ptr2 != LocServiceTimesVector.end())
17012 PreviousService =
"";
17013 ServiceAndRepeatNumTotal =
"";
17014 NumTrainsAtLoc = 0;
17016 NumPlatsAtThisLocCalculated =
false;
17018 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17020 PreviousService =
"";
17021 ServiceAndRepeatNumTotal =
"";
17022 NumTrainsAtLoc = 0;
17024 NumPlatsAtThisLocCalculated =
false;
17028 if(Ptr2 == LocServiceTimesVector.end())
17033 if(Ptr2 == LocServiceTimesVector.end())
17037 while(Ptr2->Location == Ptr1->Location)
17039 if(Ptr1->FrhMarker ==
"Frh")
17042 Ptr1->FrhMarker =
"FrhCounted";
17044 PreviousService =
"";
17045 NumTrainsAtLoc = 0;
17046 ServiceAndRepeatNumTotal =
"";
17047 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17051 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
17054 if(Ptr1->FrhMarker ==
"Frh")
17057 Ptr1->FrhMarker =
"FrhCounted";
17060 if(Ptr2 == LocServiceTimesVector.end())
17064 if(Ptr2->Location != Ptr1->Location)
17069 if(Ptr2 == LocServiceTimesVector.end())
17073 if(Ptr2->Location != Ptr1->Location)
17077 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
17079 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
17083 if(!NumPlatsAtThisLocCalculated)
17086 NumPlatsAtThisLocCalculated =
true;
17088 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17090 if(ServiceAndRepeatNumTotal ==
"")
17092 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
17093 NumTrainsAtLoc = 1;
17097 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
17100 PreviousService = Ptr2->ServiceAndRepeatNum;
17101 if(ServiceAndRepeatNumTotal ==
"")
17103 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
17104 NumTrainsAtLoc = 1;
17108 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
17111 if(Ptr1->FrhMarker ==
"Frh")
17114 Ptr1->FrhMarker =
"FrhCounted";
17117 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
17121 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
17123 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
17125 AnsiString Asterisk =
"";
17126 if(NumTrainsAtLoc > NumPlats)
17133 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17135 else if(FrhCount == 1)
17137 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17141 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
17143 LastFrhCount = FrhCount;
17144 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
17145 AtLocsPrinted =
true;
17146 ServiceAndRepeatNumTotal =
"";
17149 if(Ptr2 == LocServiceTimesVector.end())
17153 if(Ptr2->Location != Ptr1->Location)
17158 if(Ptr2 == LocServiceTimesVector.end())
17166 TTFile3 <<
"Nothing to report for trains at locations";
17168 TTFile3 <<
"\n\n\n";
17189 catch(
const Exception &e)
17191 AnsiString TTErrorFileName =
"Analysis Error.txt";
17192 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
17193 std::ofstream TTError(TTErrorFileName.c_str());
17196 ShowMessage(
"Analysis error file failed to open - can't be created");
17200 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17201 TTError << TimeNow.c_str() <<
"\n" << ArrRange <<
"\n" << ArrChecked <<
"\n" << DepRange <<
"\n" <<
17202 DepChecked <<
"\n" << AtLocChecked <<
"\n" << AnsiString(e.Message);
17204 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
17216 if((Time1 ==
"") || (Time2 ==
""))
17221 int Mins = Time1.SubString(4,2).ToInt();
17222 int Hours = Time1.SubString(1,2).ToInt();
17223 int Time1Mins = (Hours * 60) + Mins;
17224 Mins = Time2.SubString(4,2).ToInt();
17225 Hours = Time2.SubString(1,2).ToInt();
17226 int Time2Mins = (Hours * 60) + Mins;
17227 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
17239 bool &AnalysisError,
int &MaxNumberOfSameDirections)
17246 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
17248 std::list<AnsiString> ServiceList;
17250 bool EvenComma =
false;
17251 for(
int x = 1; x <= Input.Length(); x++)
17253 TempStr1 = Input[x];
17254 if(TempStr1 == AnsiString(
',') && EvenComma)
17260 TempStr2 += Input[x];
17262 if(TempStr1 == AnsiString(
','))
17264 EvenComma = !EvenComma;
17268 while(TempStr2.Length() > 0)
17270 SCPos = TempStr2.Pos(
';');
17273 OneService = TempStr2.SubString(1, SCPos - 1);
17274 ServiceList.push_back(OneService);
17275 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
17279 ServiceList.push_back(TempStr2);
17283 ServiceList.sort();
17284 ServiceList.unique();
17285 NumTrainsAtLoc = ServiceList.size();
17288 int DirectionMarker = 0;
17290 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
17292 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
17294 *SLIt = *SLIt +
"&0";
17296 SLIt3 = ServiceList.end();
17298 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
17299 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
17300 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
17302 MaxNumberOfSameDirections = 0;
17303 int SameDirectionCount = 0;
17305 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
17309 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
17315 CommaPos1 = SLIt1->Pos(
',');
17316 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
17318 SpacePos = ServiceRef1.Pos(
' ');
17322 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
17323 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
17324 if(RepeatInfo1[1] ==
'F')
17330 SpacePos = RepeatInfo1.Pos(
' ');
17331 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
17334 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
17336 AmpersandPos = AnsiTime1.Pos(
'&');
17337 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
17342 throw Exception(
"ASCLIt1 Error in " + Input);
17344 ServiceCallingLocsList1 = ASCLIt1->second;
17345 AmpersandPos = SLIt1->Pos(
'&');
17346 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
17347 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
17349 SameDirectionCount = 1;
17350 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
17352 CommaPos2 = SLIt2->Pos(
',');
17353 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
17355 SpacePos = ServiceRef2.Pos(
' ');
17359 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
17360 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
17361 if(RepeatInfo2[1] ==
'F')
17367 SpacePos = RepeatInfo2.Pos(
' ');
17368 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
17371 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
17373 AmpersandPos = AnsiTime2.Pos(
'&');
17374 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
17379 throw Exception(
"ASCLIt2 Error in " + Input);
17381 ServiceCallingLocsList2 = ASCLIt2->second;
17383 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
17385 int AmpersandPos = SLIt2->Pos(
'&');
17386 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
17387 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
17388 SameDirectionCount++;
17391 if(SameDirectionCount > MaxNumberOfSameDirections)
17393 MaxNumberOfSameDirections = SameDirectionCount;
17398 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
17401 AmpersandPos = SLIt3->Pos(
'&');
17402 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
17403 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
17406 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
17409 AmpersandPos = SLIt->Pos(
'&');
17410 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
17411 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
17412 DirectionMarker = DirectionMarkerString.ToInt();
17413 AnsiString DirectionSuffix =
"";
17415 if(DirectionMarker < 27)
17417 c = 64 + DirectionMarker;
17418 DirectionSuffix =
"," + AnsiString(c);
17420 else if(DirectionMarker < 53)
17422 c = 65 + DirectionMarker - 27;
17423 DirectionSuffix =
",A" + AnsiString(c);
17427 DirectionSuffix =
",?";
17429 *SLIt = ServiceWithoutMarker + DirectionSuffix;
17432 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
17434 Output = Output + *SLIt +
",";
17436 if(Output.Length() > 0)
17438 Output = Output.SubString(1, Output.Length() - 1);
17444 catch(
const Exception &e)
17446 AnalysisError =
true;
17458 AnsiString InternalInput = Input, Output =
"", OneService =
"";
17460 std::list<AnsiString> ServiceList;
17462 while(InternalInput.Length() > 0)
17464 CommaPos = InternalInput.Pos(
',');
17467 OneService = InternalInput.SubString(1, CommaPos - 1);
17468 ServiceList.push_back(OneService);
17469 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
17473 ServiceList.push_back(InternalInput);
17474 InternalInput =
"";
17478 ServiceList.sort();
17479 ServiceList.unique();
17480 NumTrainsAtLoc = ServiceList.size();
17481 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
17483 Output = Output + *SLIt +
",";
17485 if(Output.Length() > 0)
17487 Output = Output.SubString(1, Output.Length() - 1);
17500 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
17502 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
17507 bool LocFound =
false;
17508 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
17510 TDateTime FirstServiceTime;
17513 int Ref1Target = 0, Ref1Count = 0;
17514 int SlashPos = Ref1.Pos(
'/');
17517 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
17518 Ref1 = Ref1.SubString(1, SlashPos - 1);
17520 int Ref2Target = 0, Ref2Count = 0;
17521 SlashPos = Ref2.Pos(
'/');
17524 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
17525 Ref2 = Ref2.SubString(1, SlashPos - 1);
17527 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
17530 if((*ListPtr1) == Location)
17532 LocPtr1 = ListPtr1;
17535 if(ListPtr1->SubString(1, 3) ==
"%%%")
17537 AnsiString CDTTime = ListPtr1->SubString(4, 5);
17542 FirstServiceTime = TDateTime(-1);
17543 bool BreakFlag =
false;
17546 if(TDVIt->ServiceReference == Ref1)
17548 if(Ref1Target > Ref1Count)
17553 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
17554 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
17558 FirstServiceTime = AVIt->EventTime;
17564 FirstServiceTime = AVIt->ArrivalTime;
17570 FirstServiceTime = AVIt->DepartureTime;
17581 if(IncMinutes == -1)
17583 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
17585 if(FirstServiceTime == TDateTime(-1))
17587 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
17591 if(!Arrival && (Time1 == CDTTime))
17596 if(Arrival && (Time1 == CDTTime))
17600 if(Time1 > CDTTime)
17605 if(Time1 < CDTTime)
17618 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
17620 if((*ListPtr2) == Location)
17622 LocPtr2 = ListPtr2;
17625 if(ListPtr2->SubString(1, 3) ==
"%%%")
17627 AnsiString CDTTime = ListPtr2->SubString(4, 5);
17632 FirstServiceTime = TDateTime(-1);
17633 bool BreakFlag =
false;
17636 if(TDVIt->ServiceReference == Ref2)
17638 if(Ref2Target > Ref2Count)
17643 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
17644 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
17648 FirstServiceTime = AVIt->EventTime;
17654 FirstServiceTime = AVIt->ArrivalTime;
17660 FirstServiceTime = AVIt->DepartureTime;
17671 if(IncMinutes == -1)
17673 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
17675 if(FirstServiceTime == TDateTime(-1))
17677 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
17681 if(!Arrival && (Time2 == CDTTime))
17686 if(Arrival && (Time2 == CDTTime))
17690 if(Time2 > CDTTime)
17695 if(Time2 < CDTTime)
17710 LP1 = List1.begin();
17712 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
17714 if(ListPtr1 == List1.begin())
17718 if(ListPtr1->SubString(1, 3) ==
"%%%")
17725 LP2 = List2.begin();
17727 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
17729 if(ListPtr2 == List2.begin())
17733 if(ListPtr2->SubString(1, 3) ==
"%%%")
17743 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
17745 if(ListPtr1 == LocPtr1)
17749 if(ListPtr1->SubString(1, 3) ==
"%%%")
17753 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
17755 if(ListPtr2 == LocPtr2)
17759 if(ListPtr2->SubString(1, 3) ==
"%%%")
17763 if((*ListPtr1) == (*ListPtr2))
17780 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
17782 if(ListPtr1 == List1.end())
17786 if(ListPtr1->SubString(1, 3) ==
"%%%")
17790 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
17792 if(ListPtr2 == List2.end())
17796 if(ListPtr2->SubString(1, 3) ==
"%%%")
17800 if((*ListPtr1) == (*ListPtr2))
17817 if(ExitList.empty())
17823 AnsiString ExitLocList =
"";
17826 unsigned int Counter = 0;
17831 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
17833 ExitLocList +=
"\n";
17836 if(StartName ==
"")
17838 if(ExitList.size() == 1)
17842 return(
" at " + ID);
17847 if(ExitList.size() < 4)
17849 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
17854 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
17864 if(ExitList.size() < 4)
17866 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
17871 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
17877 if(ExitList.size() < 4)
17879 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
17880 return(
" at " + StartName);
17884 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
17885 return(
" at " + StartName);
17925 AnsiString FormatStr =
"####0.0";
17926 AnsiString AvLateArrMins =
"";
17927 AnsiString AvEarlyArrMins =
"";
17928 AnsiString AvLatePassMins =
"";
17929 AnsiString AvEarlyPassMins =
"";
17930 AnsiString AvLateDepMins =
"";
17931 AnsiString AvLateExitMins =
"";
17932 AnsiString AvEarlyExitMins =
"";
17962 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
17963 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
17975 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
17979 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
17987 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
17991 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
17999 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
18007 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
18011 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
18015 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
18019 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
18023 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
18027 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
18032 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
18036 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
18040 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
18044 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
18048 PerfFile <<
LateExits <<
" late exits" <<
'\n';
18052 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
18056 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
18060 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
18065 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
18069 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
18073 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
18077 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
18081 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
18083 TDateTime TempExcessLCDownTime;
18097 if(TempExcessLCDownTime > TDateTime(0))
18103 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
18107 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
18111 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
18115 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
18143 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
18147 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
18153 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
18157 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
18160 AnsiString AvLateMinsLocsNotReached =
"";
18166 if(LocsNotReached > 0)
18169 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
18173 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
18177 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
18189 PerfFile <<
Derailments <<
" derailments" <<
'\n';
18193 PerfFile <<
Derailments <<
" derailment" <<
'\n';
18203 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
18205 bool DerailSPADFlag =
false, CrashFlag =
false;
18207 int OverallScorePercent = 100;
18208 int TotArrDepExit = 0;
18209 double TotLateMinsFactor = 1;
18210 double MissedStopAndSPADRiskFactor = 1;
18211 double NetNegFactor = 1;
18221 OverallScorePercent = 5;
18222 DerailSPADFlag =
true;
18226 OverallScorePercent = 0;
18229 if(OverallScorePercent == 100)
18231 if(TotArrDepExit > 0)
18233 TotLateMinsFactor =
18241 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
18243 OverallScorePercent = 100 * NetNegFactor;
18246 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
18249 AnsiString OneFailureString =
", though the failure would account for some poor performance";
18250 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
18251 AnsiString AddedString =
"";
18254 AddedString = OneFailureString;
18258 AddedString = TwoOrMoreFailureString;
18260 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
18261 AnsiString Rating =
"";
18262 if(OverallScorePercent == 100)
18264 Rating =
"Perfect!";
18266 else if(OverallScorePercent >= 95)
18268 Rating =
"Excellent";
18270 else if(OverallScorePercent >= 90)
18272 Rating =
"Very good";
18274 else if(OverallScorePercent >= 80)
18278 else if(OverallScorePercent >= 70)
18282 else if(OverallScorePercent >= 60)
18284 Rating =
"Unacceptable" + AddedString;
18286 else if(OverallScorePercent >= 50)
18288 Rating =
"Poor" + AddedString;
18290 else if(OverallScorePercent >= 40)
18292 Rating =
"Bad" + AddedString;
18294 else if(OverallScorePercent >= 30)
18296 Rating =
"Very bad" + AddedString;
18298 else if(OverallScorePercent >= 20)
18300 Rating =
"Terrible" + AddedString;
18302 else if(OverallScorePercent >= 10)
18304 Rating =
"Appalling" + AddedString;
18306 else if(OverallScorePercent >= 5)
18310 Rating =
"Disastrous - potential loss of life";
18315 Rating =
"Dire" + AddedString;
18318 else if(OverallScorePercent < 5)
18322 Rating =
"Catastrophic - loss of life";
18326 Rating =
"Abysmal";
18329 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
18333 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
18335 PerfFile <<
'\n' <<
"***************************************";
18344 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
18394 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
18429 int IncrementalMinutes = 0;
18443 bool TrainOperatingFlag =
false;
18448 TrainOperatingFlag =
true;
18452 if(TrainOperatingFlag)
18460 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
18507 AnsiString HeadCode;
18511 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
18515 HCandTrainPosParam.first = HeadCode;
18516 HCandTrainPosParam.second = TrainID;
18518 if((TimeToAct >= 0) && (TimeToAct < 59.9))
18521 OpTimeToActMultiMapEntry.first = TimeToAct;
18522 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
18551 float TimeToAct = 0;
18552 int DistanceToRedSignal = 0;
18555 ContinuationEntryVecPosVector.clear();
18556 bool LaterTrain =
false;
18560 LaterTrain =
false;
18561 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
18572 if(!ContinuationEntryVecPosVector.empty())
18574 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
18576 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
18590 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
18591 AnsiString HeadCode = CTEIt->second.HeadCode;
18592 float CurrentStopTime;
18593 float LaterStopTime;
18594 float RecoverableTime;
18597 bool SigControlAndCanPassRedSignal =
false;
18601 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(1),
18603 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed);
18606 if(AvTrackSpeed < 30)
18610 if(DistanceToRedSignal == -1)
18616 int Speed = AvTrackSpeed;
18617 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
18618 if(AvTrackSpeed > MaxSpeed)
18622 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(1).SignallerControl)
18625 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
18628 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
18633 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
18634 TimeToAct += MinsBefEnter;
18637 HCandTrainPosParam.first = HeadCode;
18638 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
18641 if(TimeToAct < 59.9)
18643 OpTimeToActMultiMapEntry.first = TimeToAct;
18644 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
18656 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
18657 float &RecoverableTime,
int &AvTrackSpeed)
18666 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
18667 int DistanceToRedSignal = 0;
18668 int CumTrackSpeed = 0;
18670 int TrackSpeedCount = 0;
18680 int CurrentElement = TrackVectorPosition;
18681 int CurrentEntryPos = TrackVectorPositionEntryPos;
18686 CurrentStopTime = 0;
18688 RecoverableTime = 0;
18689 if(CurrentElement == -1)
18694 int CurrentExitPos;
18699 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
18703 CurrentExitPos = 1;
18707 CurrentExitPos = 3;
18712 CurrentExitPos = 0;
18748 CurrentStopTime = float(TimeToDepart);
18754 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
18765 else if(SigControlAndCanPassRedSignal)
18770 if((NextEntryPos == 0) || (NextEntryPos == 2))
18791 CurrentElement = NextElement;
18792 CurrentEntryPos = NextEntryPos;
18793 CurrentExitPos = NextExitPos;
18805 int LaterStopNumber = 0;
18809 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
18818 if(CurrentEntryPos > 1)
18838 bool StopRequired =
false;
18855 int TrainOnElement;
18862 if(CurrentEntryPos > 1)
18871 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
18880 double StopTimeDouble;
18893 if(StopTimeDouble < 0.5)
18895 StopTimeDouble = 0.5;
18899 LaterStopTime += float(StopTimeDouble);
18900 RecoverableTime += StopTimeDouble - 0.5;
18901 if((LaterStopNumber == 1) && (TrainID > -1))
18909 if((AVPtr + 1)->FormatType ==
TimeLoc)
18913 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
18915 if(StopTimeDouble < 0.5)
18917 StopTimeDouble = 0.5;
18920 LaterStopTime += float(StopTimeDouble);
18921 RecoverableTime += StopTimeDouble - 0.5;
18922 if((LaterStopNumber == 1) && (TrainID > -1))
18938 if(NextElement == -1)
18947 if((NextEntryPos == 0) || (NextEntryPos == 2))
18968 CurrentElement = NextElement;
18969 CurrentEntryPos = NextEntryPos;
18970 CurrentExitPos = NextExitPos;
18974 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
18989 float MaxAllowableSpeed;
18991 if(TrackSpeedCount > 0)
18993 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
18997 if(CurrentEntryPos > 1)
19007 float KmPerLocationStop;
19009 if(LaterStopNumber > 0)
19011 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
19012 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
19016 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
19020 if(AvTrackSpeed > MaxAllowableSpeed)
19022 AvTrackSpeed = MaxAllowableSpeed;
19025 return(DistanceToRedSignal);